home *** CD-ROM | disk | FTP | other *** search
- /*-------------------------------------------------------------------
-
- AOCE Post Office Protocol (POP) / Simple Mail Transfer Protocol (SMTP)
- Mail Service Access Module
-
- written by Steve Falkenburg-- MacDTS
- ©1991-1993 Apple Computer, Inc.
-
- --------------
- change history
- --------------
-
- SJF 02/19/93 update for beta build b1
- SJF 10/29/92 update to a11 a11
- SJF 06/08/92 update to a8 a8
- SJF 02/15/92 first working version a4.5
- SJF 10/16/91 initial coding a3
-
- ---------------------------------------------------------------------*/
-
- #ifndef __OCE__
- #include <OCE.h>
- #endif
-
- #ifndef __OCEMAIL__
- #include <OCEMail.h>
- #endif
-
- #include "const.h"
- #include "gwerrors.h"
- #include "mytypes.h"
- #include "globals.h"
- #include "utils.h"
- #include "spoolsystem.h"
- #include "gatewaystuff.h"
- #include "authstuff.h"
- #include "errorhandling.h"
-
- #include "spooltoexternal.h"
- #include "spoolfromaoce.h"
- #include "spooltoaoce.h"
- #include "reports.h"
-
- #include "gatewayget.h"
-
-
- // PeriodicCheckGet
- //
- // when the toolbox thinks that it's time to check for mail, this function is called, in addition
- // to being called on startup of the gateway
- //
- OSErr PeriodicCheckGet(void)
- {
- short slotIndex,arrIndex;
- SlotSpec *slotSpec;
- OSErr err = noErr;
- unsigned long dateTime;
-
- TraceExecution("\pPeriodicCheckGet");
-
- GetDateTime(&dateTime);
-
- for (slotIndex = arrIndex = 0; (err==noErr) && (slotIndex<gNumSlots); arrIndex++) {
- if ((gLocation != 0) && (gSlotDatabase[arrIndex].locationActive & MailLocationMask(gLocation))
- && gSlotDatabase[arrIndex].enabled) { // if the slot is in use, process it
- slotIndex++;
- slotSpec = &gSlotDatabase[arrIndex];
- if (slotSpec->dirIdentity.valid) {
- EnterAuthCriticalSection(); // don't allow locking of local identity while we're here
- if (TimeToCheckGet(&slotSpec->stdInfo.sendReceiveTimer,slotSpec->lastCheckGet,dateTime)) {
- err = DoSlotGet(slotSpec);
- if (err==noErr)
- slotSpec->lastCheckGet = dateTime;
- }
- ExitAuthCriticalSection();
- }
- }
- else slotIndex++; // index past slots that are disabled
- }
- return err;
- }
-
-
- // TimeToCheckGet
- //
- // returns true if it's time to check for mail. this function assumes the mailtimers are
- // in minutes, not seconds, since this seems to be what the toolbox is using for its scheduling
- // of eppcs. note that the OCEMail.h header file specifies that these values are in seconds.
- //
- Boolean TimeToCheckGet(MailTimers *mailTimer,unsigned long lastCheck,unsigned long curTime)
- {
- DateTimeRec dtRec;
- unsigned long midnightSecs;
-
- switch (mailTimer->sendTimeKind) {
- case kMailTimerOff:
- return false; // never check if there is no interval
- break;
- case kMailTimerFrequency: // check if past frequency+lastCheck
- if (mailTimer->send.frequency==0)
- return false;
- return ((lastCheck + (60*mailTimer->send.frequency))<curTime);
- break;
- case kMailTimerTime: // check at a specific time
- if ((lastCheck + kOneDaySecs) > curTime)
- return false;
- Secs2Date(curTime,&dtRec); // get date of last midnight
- dtRec.hour = 0;
- dtRec.minute = 0;
- dtRec.second = 0;
- Date2Secs(&dtRec,&midnightSecs);
- return ( (midnightSecs+(60*mailTimer->send.connectTime)) > curTime );
- break;
- }
- return false;
- }
-
-
- // DoSlotGet
- //
- // when we've determined that it's actually time to do a "get" (send to external system) this
- // function is called by PeriodicCheckGet.
- //
- OSErr DoSlotGet(SlotSpec *slot)
- {
- OSErr err,enumErr,err2;
- MSAMEnumeratePB gwp;
- EnumOutQReply enumBlock;
- long nextMsgSeq;
- MailMsgRef msgRef;
- FSSpec spoolSpec;
-
- TraceExecution("\pDoSlotGet");
-
- // first, we pull all the pending letters out of the AOCE slot and spool them
-
- nextMsgSeq = 1;
-
- err = noErr;
-
- do {
- gwp.ioCompletion = (ProcPtr)MSAMCompletion;
- gwp.queueRef = slot->outQueue;
- gwp.startSeqNum = nextMsgSeq;
- gwp.buffer.bufferSize = sizeof(EnumOutQReply);
- gwp.buffer.buffer = (Ptr)&enumBlock;
- MSAMEnumerate((MSAMParam *)&gwp,true);
- enumErr = WaitPBDone(&gwp);
- nextMsgSeq = gwp.nextSeqNum;
- if (enumErr==noErr && gwp.buffer.dataSize>sizeof(short) && (enumBlock.message.done==false)) {
-
- err = CreateSpoolFile(&spoolSpec); // make our spool file
- if (err!=noErr)
- break;
-
- // here, the message is spooled to the common data area, and then sent to the external gateway
-
- err = GetSlotMessage(slot->outQueue,&enumBlock.message,&msgRef,&spoolSpec);
- if (err==noErr) {
- err = SpoolToExternalGW(&spoolSpec,slot);
- err2 = DoneSlotMessage((err==noErr),slot->outQueue,&enumBlock.message,&spoolSpec,msgRef);
- if (err==noErr)
- err = err2;
- }
-
- if (err!=noErr) {
- RemoveSpoolFile(&spoolSpec);
- break;
- }
-
- err = RemoveSpoolFile(&spoolSpec);
- if (err!=noErr)
- break;
- }
- }
- while (enumErr==noErr && nextMsgSeq!=0);
-
- // error retry mechanism- only report errors after we fail a number of times
- // specified in kAllowedRetries
-
- err = RetrySlotError(err,slot,false);
-
- return err;
- }
-
-
- OSErr GetSlotMessage(MSAMQueueRef qid,MSAMEnumerateOutQReply *msg,MailMsgRef *retMsgRef,FSSpec *spoolSpec)
- {
- OSErr err;
- MSAMParam gwp;
- MailMsgRef msgRef;
-
- // mark message as being sent
-
- gwp.header.ioCompletion = (ProcPtr)MSAMCompletion;
- gwp.pmsamSetStatus.queueRef = qid;
- gwp.pmsamSetStatus.seqNum = msg->seqNum;
- gwp.pmsamSetStatus.msgHint = 0;
- gwp.pmsamSetStatus.status = kPMSAMStatusSending;
- err = PMSAMSetStatus(&gwp,true);
- err = WaitPBDone(&gwp);
- if (err!=noErr)
- return err;
-
- // open message
-
- gwp.msamOpen.queueRef = qid;
- gwp.msamOpen.seqNum = msg->seqNum;
- MSAMOpen(&gwp,true);
- err = WaitPBDone(&gwp);
- if (err!=noErr) {
- return err;
- }
- msgRef = gwp.msamOpen.mailMsgRef;
-
- // put message into spool area
-
- err = SpoolFromAOCE(msgRef,spoolSpec);
- if (err!=noErr) {
- // might log this error with error reporting log
- // close message
- gwp.header.ioCompletion = (ProcPtr)MSAMCompletion;
- gwp.msamClose.mailMsgRef = msgRef;
- MSAMClose(&gwp,true);
- WaitPBDone(&gwp);
- }
-
- *retMsgRef = msgRef;
- return err;
- }
-
-
- // we mark recipients, send delivery reports, close the message
- //
- // *** NOTE
- //
- // a14 and later note: we no longer delete the outging messages from the queue
- // as per the "Public API deltas" document corresponding to the queue mgr redesign
- //
- // ********
-
- OSErr DoneSlotMessage(Boolean sent,MSAMQueueRef qid,MSAMEnumerateOutQReply *msg,FSSpec *spoolSpec,MailMsgRef msgRef)
- {
- MSAMParam gwp;
- OSErr err;
- unsigned long bufferLen;
- short recipientIndex,spoolIndex;
-
- // send the recipient reports for all recipients
-
- err = GenerateDeliveryReport(sent,spoolSpec);
- if (err!=noErr)
- return err;
-
- // mark each recipient
-
- if (sent) {
- for (spoolIndex=0,err=noErr; err==noErr; spoolIndex++) {
- bufferLen = sizeof(short);
- err = GetFromSpool(spoolSpec,kRecipientType,kReportCreator,spoolIndex,(Ptr)&recipientIndex,&bufferLen,0);
- if ((err==noErr)||(err==kMoreData)) {
- err = MarkRead(msgRef,recipientIndex);
- if (err!=noErr)
- return err;
- }
- }
- }
-
- // close message
-
- gwp.header.ioCompletion = (ProcPtr)MSAMCompletion;
- gwp.msamClose.mailMsgRef = msgRef;
- MSAMClose(&gwp,true);
- err = WaitPBDone(&gwp);
- if (err!=noErr)
- return err;
-
- // change status to error if it didn't send
-
- if (!sent) {
- gwp.header.ioCompletion = (ProcPtr)MSAMCompletion;
- gwp.pmsamSetStatus.queueRef = qid;
- gwp.pmsamSetStatus.seqNum = msg->seqNum;
- gwp.pmsamSetStatus.msgHint = 0;
- gwp.pmsamSetStatus.status = kPMSAMStatusError;
- err = PMSAMSetStatus(&gwp,true);
- err = WaitPBDone(&gwp);
- if (err!=noErr)
- return err;
- }
-
- // mark that we sent message
-
- msg->done = true;
- return err;
- }
-
-
-
- OSErr MarkRead(MailMsgRef msgRef,short recipIndex)
- {
- MSAMnMarkRecipientsPB gwp;
- short markMsgs[2];
- OSErr err;
-
- TraceExecution("\pMarkRead");
-
- markMsgs[0] = 1; // count
- markMsgs[1] = recipIndex; // index to mark
-
- gwp.ioCompletion = (ProcPtr)MSAMCompletion;
- gwp.mailMsgRef = msgRef;
- gwp.buffer.buffer = (Ptr)markMsgs;
- gwp.buffer.bufferSize = sizeof(short) + sizeof(short);
-
- MSAMnMarkRecipients((MSAMParam *)&gwp,true);
- err = WaitPBDone(&gwp);
-
- #ifdef kDEBUG
- if (err==kOCEInvalidIndex) {
- DebugStr("\pGot kOCEInvalidIndex");
- }
- #endif
-
- return err;
- }
-
-